<!--
x-html.html v0.0.20131220
(c) 2013 Joachim Wester
MIT license
https://github.com/PuppetJs/x-html
-->
<script>
  (function () {
    Object.defineProperty(Node.prototype, 'model', {
      get: function () {
        if (this.bindings) {
          return (this.bindings.content || this.bindings.value).model; //`content` is in DOM and `value` is in Shadow DOM
        }
      }
    });

    function loadTemplate(customElement) {
      var val = customElement.getAttribute('content');
      if (val && (val.indexOf('/') === 0 || val.indexOf('./') === 0)) {
        //val is a URL, load the partial from the HTTP server/cache
        var oReq = new XMLHttpRequest();
        oReq.onload = function (event) {
          reattachTemplate(customElement, event.target.responseText);
        };
        oReq.open("GET", val, true);
        oReq.send();
      }
      else {
        //val is HTML code, insert the partial from the string
        reattachTemplate(customElement, val);
      }
    }

    function reattachTemplate(customElement, html) {
      customElement.innerHTML = '<template bind>' + html + '</template>';

      var template = customElement.firstChild;
      var content = template.content;

      var specialElems = content.querySelectorAll(['style', 'link[rel=stylesheet]', 'script']);
      specialElems = Array.prototype.slice.call(specialElems, 0); //convert to array
      specialElems.forEach(function (elem) {
        elem.parentNode.removeChild(elem); //avoid being processed by HTMLImports
      });

      HTMLImports.importer.load(content, function () {
        if (content.scripts === void 0) {
          content.scripts = [];
          //workaround HTMLImport error "TypeError: Cannot read property 'length' of undefined "
          //this can be removed when https://github.com/Polymer/HTMLImports/issues/40 is fixed
        }
        HTMLImports.parser.parse(content);
        template.model = customElement.model;

        specialElems.forEach(function (elem) {
          if (elem.nodeName === 'STYLE') {
            customElement.appendChild(elem);
          }
          else if (elem.nodeName === 'LINK') { //appending <link rel="stylesheet"> to Shadow DOM does not have any effect (9 Nov, 2013)
            var style = document.createElement('style');
            style.innerHTML = '@import url(' + elem.getAttribute('href') + ');';
            setTimeout(function () { //must be async, otherwise custom elements in demo puppetjs/lab/wc/page_2 display improperly
              customElement.appendChild(style);
            }, 0);
          }
          else if (elem.nodeName === 'SCRIPT') {
            setTimeout(function () { //must be async
              executeComponentScript(elem.textContent, customElement, 'script')
            }, 0);
          }
        });
      });
    }

    /**
     * Function that executes script (that is ignored by browser's .innerHTML)
     * @source Polymer's HTMLElementElement.js
     */
    function executeComponentScript(inScript, inContext, inName) {
      // set (highlander) context
      context = inContext;
      // source location
      var owner = context.ownerDocument;
      var url = (owner._URL || owner.URL || owner.impl
        && (owner.impl._URL || owner.impl.URL));
      // ensure the component has a unique source map so it can be debugged
      // if the name matches the filename part of the owning document's url,
      // use this, otherwise, add ":<name>" to the document url.
      var match = url.match(/.*\/([^.]*)[.]?.*$/);
      if (match) {
        var name = match[1];
        url += name != inName ? ':' + inName : '';
      }
      // compose script
      var code = "__componentScript('"
          + inName
          + "', function(){"
          + inScript
          + "});"
          + "\n//# sourceURL=" + url + "\n"
        ;
      // inject script
      eval(code);
    }

    var context;

    // global necessary for script injection
    window.__componentScript = function (inName, inFunc) {
      inFunc.call(context);
    };

    var XHTMLPrototype = Object.create(HTMLElement.prototype);
    XHTMLPrototype.createdCallback = function () {
      var customElement = this;
      loadTemplate(customElement);

      var observer = new MutationObserver(function (mutations) {
        mutations.forEach(function (mutation) {
          if (mutation.type === "attributes" && mutation.attributeName === "content") {
            loadTemplate(customElement);
          }
        });
      });
      observer.observe(this, {
        attributes: true
      });
    };
    XHTMLPrototype.readyCallback = XHTMLPrototype.createdCallback; //required for compatibility with polymer.js < 20130816

    document.register('x-html', {
      prototype: XHTMLPrototype
    });
  })();
</script>